﻿using SuperX.Common;
using SuperX.Common.APIManager;
using SuperX.Common.BasicService;
using SuperX.Common.Log;
using SuperX.Common.Object;
using SuperX.Common.Respository;
using SuperX.DataService;
using SuperX.DataService.Abstract;
using SuperX.Helper;
using SuperX.DeviceService.Ledger;
using SuperX.DeviceService.Template;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;

namespace SuperX.DeviceService
{
    public class DeviceServer : HostService
    {
        public override string ServiceType { get; set; }

        public static int RunIndex { get; set; } = 1;

        public DeviceConfig Config { get; set; }

        private DynamicApiController Controller;

        private DynamicApiController TemplateController;

        internal EquipmentManager EquipmentManager { get; set; }

        public override bool Exit()
        {
            return true;
        }

        public override bool Init()
        {
            Controller = new DeviceController(this);
            TemplateController = new DeviceTemplateController(this);
            return true;
        }

        public override bool Load(string fileName)
        {
            FileName = fileName;
            Repository = new JsonRepository(FileName);
            Repository.Load(typeof(DeviceConfig));
            Config = Repository.Model as DeviceConfig;
            if (Config == null)
            {
                CreateCfgFile(); //配置文件格式错误会重新创建，默认驱动分组无法正常加入
            }
            //判断默认驱动是否存在
            var defaultDriverCfgPath = $"{AppDomain.CurrentDomain.BaseDirectory}{Config.DefaultDriverCfgName}";
            if (!File.Exists(defaultDriverCfgPath)) CreateDefaultDriverCfgFile(defaultDriverCfgPath);
            Config.DefaultDriverConfig = GetDefaultDriverConfig();
            return true;
        }

        public override bool SaveAs(string fileName)
        {
            Repository = new JsonRepository(fileName) { Model = Config };
            Repository.Save();
            return true;
        }

        public override bool Start()
        {
            Logger.Info($"{this.GetType().Name}启动");
            DataManager = new DataManager(Config, this);
            TemplateManager = new TemplateManager(Config, this);
            EquipmentManager = new EquipmentManager(Config);
            DataManager.Init();
            DataManager.Start();
            return true;
        }

        public override bool Stop()
        {
            Logger.Info($"{GetType().Name}停止...");
            DataManager.Stop();
            Controller = null;
            DataManager = null;
            TemplateManager = null;
            EquipmentManager = null;
            TemplateController = null;
            return true;
        }

        public bool Restart()
        {
            Stop();
            Thread.Sleep(500);
            Init();
            return Start();
        }

        public DataManager DataManager { get; set; }

        internal TemplateManager TemplateManager { get; set; }

        private void CreateCfgFile()
        {
            DeviceConfig config = new DeviceConfig();
            Config = config;
            SaveAs(FullFileName);
        }

        #region Not Use

        private DriverConfig CreateSamsungDriver()
        {
            Dictionary<string, ArgumentModel> _argumentYamaha = new Dictionary<string, ArgumentModel>();
            _argumentYamaha["MesDeviceId"] = ArgumentModel.CreateArgument("NPM-01", "MesDeviceId");
            _argumentYamaha["FilePath"] = ArgumentModel.CreateArgument("D:\\data\\三星\\生产日志\\料站表", "料站表");
            _argumentYamaha["BackupPath"] = ArgumentModel.CreateArgument("D:\\data\\backup\\Samsung-01", "backup");
            _argumentYamaha["FSFilePath"] = ArgumentModel.CreateArgument("D:\\data\\三星\\生产日志\\抛料表", "抛料表");
            DriverConfig yamahaConfig = new DriverConfig()
            {
                Name = "Samsung",
                AssemblyName = "SuperX.Samsung.dll",
                ClassFullName = "SuperX.Samsung.SamsungDriverReader",
                Argument = _argumentYamaha,
                PreDriverName = "Samsung"
            };
            return yamahaConfig;
        }

        private static DriverConfig CreateYamahaMotorDriver()
        {
            Dictionary<string, ArgumentModel> _argumentYamaha = new Dictionary<string, ArgumentModel>();
            _argumentYamaha["LocalUdpPort"] = ArgumentModel.CreateArgument("8881", "本地端口");
            _argumentYamaha["ConnectUdpPort"] = ArgumentModel.CreateArgument("6109", "连接端口");
            _argumentYamaha["ReportPort"] = ArgumentModel.CreateArgument("6110", "报告端口");
            _argumentYamaha["CmdTcpPort"] = ArgumentModel.CreateArgument("6111", "命令端口");
            _argumentYamaha["ServerName"] = ArgumentModel.CreateArgument("192.168.130.31", "设备IP");
            _argumentYamaha["LocalIp"] = ArgumentModel.CreateArgument("192.168.130.103", "本地IP");
            DriverConfig yamahaConfig = new DriverConfig()
            {
                Name = "Yamaha",
                AssemblyName = "SuperX.YamahaMotor.dll",
                ClassFullName = "SuperX.YamahaMotor.YamahaMotorDriver",
                Argument = _argumentYamaha,
                PreDriverName = "Yamaha"
            };
            return yamahaConfig;
        }

        private static DriverConfig CreateSimulatorDriver()
        {
            List<TagConfig> tagMetas = new List<TagConfig>();
            TagConfig tagMeta = new TagConfig()
            {
                Name = "Receiving1_AlmAck",
                DataType = DataType.BOOL,
                Size = 1,
                Address = "Channel4.Receiving1.K0008.10",
                Cycle = 0,
                Minimum = 0,
                Maximum = 9999999,
                Archive = true,
            };
            tagMetas.Add(tagMeta);
            List<GroupConfig> groupConfigs = new List<GroupConfig>();
            GroupConfig groupConfig = new GroupConfig()
            {
                Name = "Receiving1",
                UpdateRate = 300,
                DeadBand = 0,
                IsActive = true,
            };
            foreach (var item in tagMetas)
            {
                groupConfig.TagGroups.Add(item);
            }
            groupConfigs.Add(groupConfig);
            Dictionary<string, ArgumentModel> _argument = new Dictionary<string, ArgumentModel>();
            _argument["FileName"] = ArgumentModel.CreateArgument("", "文件名");
            _argument["ServerName"] = ArgumentModel.CreateArgument("", "服务器");
            _argument["TimeOut"] = ArgumentModel.CreateArgument("240", "超时");
            DriverConfig driverConfig = new DriverConfig()
            {
                Name = "Simulator",
                AssemblyName = "SuperX.Simulator.dll",
                ClassFullName = "SuperX.Simulator.SimulatorDriver",
                Argument = _argument,
                PreDriverName = "Simulator",
                Enabled = true
            };
            foreach (var item in groupConfigs)
            {
                driverConfig.Groups.Add(item);
            }

            return driverConfig;
        }

        #endregion Not Use

        private void CreateDefaultDriverCfgFile(string defaultDriverCfgPath)
        {
            List<DriverConfig> driverConfigs = new List<DriverConfig>();
            Dictionary<string, ArgumentModel> _argument = new Dictionary<string, ArgumentModel>();
            _argument["FileName"] = ArgumentModel.CreateArgument("", "文件名");
            _argument["ServerName"] = ArgumentModel.CreateArgument("", "服务名");
            _argument["TimeOut"] = ArgumentModel.CreateArgument("240", "超时时间");
            driverConfigs.Add(new DriverConfig()
            {
                AssemblyName = "SuperX.Simulator.dll",
                ClassFullName = "SuperX.Simulator.SimulatorDriver",
                Name = "Simulator",
                Argument = _argument,
                PreDriverName = "Simulator"
            });
            SaveDefaultDriverCfg(defaultDriverCfgPath, driverConfigs);
        }

        public bool SaveDefaultDriverCfg(string fileName, List<DriverConfig> driverConfigs)
        {
            IRepository repository = new JsonRepository(fileName) { Model = driverConfigs };
            repository.Save();
            return true;
        }

        /// <summary>
        /// 获取预配置的驱动配置
        /// </summary>
        /// <returns></returns>
        public List<DriverConfig> GetDefaultDriverConfig()
        {
            IRepository Repository = new JsonRepository(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Config.DefaultDriverCfgName));
            Repository.Load(typeof(List<DriverConfig>));
            var DriverConfigs = Repository.Model as List<DriverConfig>;
            if (DriverConfigs == null) return new List<DriverConfig>();
            DriverConfigs.ForEach(e => { e.Name = e.PreDriverName; });
            return DriverConfigs;
        }

        /// <summary>
        /// 获取Python编译器提示
        /// </summary>
        /// <returns></returns>
        public List<PythonScriptModel> GetPythonScripts()
        {
            List<PythonScriptModel> list = new List<PythonScriptModel>();
            var APICollection = BasicServiceManager.GetProjService().Project.Objects.Values.OfType<IAPIController>();
            foreach (var item in APICollection)
            {
                Type t = item.GetType();
                object[] records = t.GetCustomAttributes(typeof(PythonScriptAttribute), false);
                foreach (PythonScriptAttribute r in records)
                {
                    var PythonScriptModel = new PythonScriptModel
                    {
                        label = r.label,
                        apply = r.apply,
                        type = r.type,
                        detail = r.detail
                    };
                    list.Add(PythonScriptModel);
                }

                var members = t.GetMethods();
                foreach (var m in members)
                {
                    foreach (Attribute attribute in m.GetCustomAttributes(false))
                    {
                        if (attribute is PythonScriptAttribute scriptAttribute)
                        {
                            list.Add(new PythonScriptModel()
                            {
                                label = scriptAttribute.label,
                                apply = scriptAttribute.apply,
                                type = scriptAttribute.type,
                                detail = scriptAttribute.detail
                            });
                        }
                    }
                }
            }

            Dictionary<string, IIOTag> dics = DataManager.IOTagGroup;
            foreach (var item in dics)
            {
                if (item.Key == null) continue;
                if (item.Key.IndexOf(".") > -1)
                {
                    foreach (var tagitem in item.Key.Split('.'))
                    {
                        list.Add(new PythonScriptModel()
                        {
                            label = tagitem,
                            apply = tagitem,
                            type = "text",
                            detail = ""
                        });
                    }
                }
                else
                {
                    list.Add(new PythonScriptModel()
                    {
                        label = item.Key,
                        apply = item.Key,
                        type = "text",
                        detail = ""
                    });
                }
            }
            //增加获取当前变量、分组、值、设备的快捷方式
            list.Add(new PythonScriptModel()
            {
                label = _thisDevice,
                apply = _thisDevice,
                type = "text",
                detail = ""
            });
            list.Add(new PythonScriptModel()
            {
                label = _thisGroup,
                apply = _thisGroup,
                type = "text",
                detail = ""
            });
            list.Add(new PythonScriptModel()
            {
                label = _thisTag,
                apply = _thisTag,
                type = "text",
                detail = ""
            });
            list.Add(new PythonScriptModel()
            {
                label = _thisValue,
                apply = _thisValue,
                type = "text",
                detail = ""
            });
            return list;
        }

        private const string _thisDevice = "$this.device$";
        private const string _thisGroup = "$this.group$";
        private const string _thisTag = "$this.tag$";
        private const string _thisValue = "$this.value$";

        public void SaveHDAConfig(Dictionary<string, string> tagsKey)
        {
        }

        public void SaveWebSocketConfig()
        {
        }
    }

    public class IoItem : BasicObject
    {
    }
}